;; Tests for the nested-vector implementation

;; by Konrad Hinsen
;; last updated February 20, 2010

;; Copyright (c) Konrad Hinsen, 2009-2010. All rights reserved.  The use
;; and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this
;; distribution.  By using this software in any fashion, you are
;; agreeing to be bound by the terms of this license.  You must not
;; remove this notice, or any other, from this software.

(ns multiarray-tests-nested-vectors
  (:use [multiarray.protocol]
	[clojure.test :only (deftest is are run-tests)])
  (:require [multiarray.nested-vectors :as implementation]))

(deftest shape-test
  (are [x y] (= x y)
       (shape 1)             []
       (shape [1 2 3 4])     [4]
       (shape [[1 2] [3 4]]) [2 2]
       (shape '(1 2 3))      [])
  (is (thrown? Exception (shape [1 [2]]))))

(deftest shape-test-zeros
  (doseq [s [ [2] [3 2] [4 1 2] ]]
    (is (= (shape (implementation/zeros s)) s)))
  (is (thrown? Exception (implementation/zeros [1 0 2]))))

(deftest rank-test
  (are [x y] (= x y)
       (rank 1)              0
       (rank [1 2 3 4])      1
       (rank [[1 2] [3 4]])  2
       (rank '(1 2 3))       0)
  (is (thrown? Exception (rank [1 [2]]))))

(deftest rank-test-zeros
  (are [x y] (= (rank (implementation/zeros x)) y)
       [2]     1
       [3 2]   2
       [3 1 2] 3))

(deftest type-test
  (are [x y] (= (element-class x) y)
       [1 2 3]           Integer/TYPE
       [1 nil]           Object
       [2/3 3]           Object
       [[1 2] [3.0 4.0]] Double/TYPE))

(deftest element-test
  (are [x y] (= (vec (elements x)) y)
       [1 2 3]       [1 2 3]
       [[1 2] [3 4]] [1 2 3 4]
       [1 2.5 4]     [1 2.5 4]))

(deftest element-array-test
  (are [x y] (= (vec (element-array x)) y)
       [1 2 3]       [1 2 3]
       [[1 2] [3 4]] [1 2 3 4]
       [1 2.5 4]     [1. 2.5 4.])
  (are [x y] (= (class (aget (element-array x) 0)) y)
       [1 2 3]       Integer
       [[1 2] [3 4]] Integer
       [1 2.5 4]     Double))

(deftest reshape-test
  (are [x y z] (= (reshape x y) z)
       [1 2 3 4] [2 2]             [[1 2] [3 4]]
       [[[1] [2]] [[3] [4]]] [2 2] [[1 2] [3 4]]
       [[[1]]] [1]                 [1]
       [1 2 3] [2 2]               [[1 2] [3 1]]
       [[1 2] [3 4]] [3]           [1 2 3]
       [] [2 0]                    [[] []])
  (is (thrown? Exception (reshape [] [2 0 1])))
  (doseq [sh [[2 2 3 3] [3 2 6] [2 1 3 1 3 1 1 2] [4 9] [36 1]]]
    (let [flat (vec (range 36))
	  ma (reshape flat sh)]
      (is (= (shape ma) sh))
      (is (= (vec (elements ma)) flat)))))

(deftest range-test
  (doseq [r [[10] [1 7 2] [10 0 -1]]]
    (is (= (vec (apply range r)) (apply implementation/ma-range r)))))

(deftest sample-test
  (are [x y] (= x y)
       (sample (implementation/ma-range 10) 0 1 7 2)
           (implementation/ma-range 1 7 2)
       (sample [[1 2] [3 4]] 0 1 2 1) [[3 4]]
       (sample [[1 2] [3 4]] 1 1 2 1) [[2] [4]]
       (sample [1 2 3] 0 2 -1 -1) [3 2 1]
       (sample [[1 2] [3 4]] 0 1 -1 -1) [[3 4] [1 2]]
       (sample [[1 2] [3 4]] 1 1 -1 -1) [[2 1] [4 3]]))

(deftest slice-test
  (are [x y] (= x y)
       (slice (implementation/ma-range 10) 0 3)  3
       (slice [[1 2] [3 4]] 0 1) [3 4]
       (slice [[1 2] [3 4]] 1 1) [2 4]))

(deftest transpose-test
  (are [x y] (= (transpose x) y)
       [1 2 3]         [1 2 3]
       [[1 2] [3 4]]   [[1 3] [2 4]]
       [[[1] [2] [3]]] [[[1] [2] [3]]])
  (are [x y z] (= (shape (transpose (implementation/zeros x) y)) z)
       [2 3]   [1 0]  [3 2]
       [5 1 2] [0 1 2] [5 1 2]
       [5 1 2] [1 2 0] [1 2 5]
       [5 1 2] [2 0 1] [2 5 1]
       [5 1 2] [0 2 1] [5 2 1]
       [5 1 2] [2 1 0] [2 1 5]
       [5 1 2] [1 0 2] [1 5 2]))

(run-tests)
